/**
 * Unified Timeline Context Provider
 *
 * This provider replaces the multiple context layers with a single,
 * clean context system that properly handles all timeline props.
 */
import React, {
  FunctionComponent,
  useCallback,
  useMemo,
  useState,
  useEffect,
  createContext,
  useContext,
} from 'react';
import {
  TimelineProps as TimelinePropsModel,
  TextDensity,
  ButtonTexts,
  SlideShowType,
} from '@models/TimelineModel';
import { Theme } from '@models/Theme';
import {
  getDefaultButtonTexts,
  getDefaultClassNames,
  getDefaultThemeOrDark,
  getSlideShowType,
} from '@utils/index';
import { useMatchMedia } from '../effects/useMatchMedia';
import { TimelineI18nConfig } from '@models/TimelineI18n';
import { useI18n } from '@hooks/useI18n';
import { createTextResolver, TextResolver } from '@utils/textResolver';

// ==========================================
// CONTEXT INTERFACES
// ==========================================

/**
 * Static configuration that rarely changes
 */
export interface TimelineStaticConfig {
  // Core layout
  mode: NonNullable<TimelinePropsModel['mode']>;
  cardHeight: number | 'auto';
  cardWidth: number;
  cardLess: boolean;
  flipLayout: boolean;
  itemWidth: number;
  lineWidth: number;

  // Media configuration
  mediaHeight: number;
  mediaSettings: {
    align: 'left' | 'right' | 'center';
    fit: 'cover' | 'contain' | 'fill' | 'none';
  };

  // Timeline point configuration
  timelinePointDimension: number;
  timelinePointShape: 'circle' | 'square' | 'diamond';

  // Interaction settings
  disableNavOnKey: boolean;
  disableAutoScrollOnClick: boolean;
  disableInteraction: boolean;
  disableClickOnCircle: boolean;
  disableTimelinePoint: boolean;

  // UI features
  enableBreakPoint: boolean;
  enableDarkToggle: boolean;
  enableLayoutSwitch: boolean;
  enableQuickJump: boolean;
  focusActiveItemOnLoad: boolean;
  highlightCardsOnHover: boolean;

  // Cards and content
  borderLessCards: boolean;
  cardPositionHorizontal: 'TOP' | 'BOTTOM';
  parseDetailsAsHTML: boolean;
  useReadMore: boolean;
  textOverlay: boolean;
  contentAlignment: {
    horizontal: 'left' | 'center' | 'right' | 'stretch';
    vertical: 'top' | 'center' | 'bottom' | 'stretch';
  };

  // Scrolling
  scrollable: boolean | { scrollbar: boolean };

  // Toolbar
  toolbarPosition: 'top' | 'bottom';
  disableToolbar: boolean;
  toolbarSearchConfig:
    | {
        width?: string;
        maxWidth?: string;
        minWidth?: string;
        inputWidth?: string;
        inputMaxWidth?: string;
      }
    | undefined;

  // Slideshow
  slideItemDuration: number;
  showProgressOnSlideshow: boolean;
  showOverallSlideshowProgress: boolean;

  // Misc
  titleDateFormat: string;
  uniqueId: string;
  nestedCardHeight: number;
  contentDetailsHeight: number;
  responsiveBreakPoint: number;
  noUniqueId: boolean;
  isChild: boolean;
}

/**
 * Dynamic state that changes frequently
 */
export interface TimelineDynamicState {
  isDarkMode: boolean;
  isMobile: boolean;
  showAllCardsHorizontal: boolean;
  textContentDensity: TextDensity;

  // Actions
  toggleDarkMode: () => void;
  updateShowAllCardsHorizontal: (state: boolean) => void;
  updateTextContentDensity: (density: TextDensity) => void;
}

/**
 * Memoized objects that change less frequently
 */
export interface TimelineMemoizedObjects {
  theme: Theme;
  buttonTexts: ButtonTexts;
  classNames: Record<string, string>;
  fontSizes: Record<string, string>;
  isDarkMode: boolean;
  semanticTags: Record<string, string>;
  slideShowType: SlideShowType;
  googleFonts: any;
  i18nConfig: TimelineI18nConfig | undefined;
  i18nHelper: ReturnType<typeof useI18n>;
  textResolver: TextResolver;
}

/**
 * Combined context interface
 */
export interface TimelineContextValue
  extends TimelineStaticConfig, TimelineDynamicState, TimelineMemoizedObjects {
  // Computed values
  computedCardHeight: number | 'auto';
  computedActiveItemIndex: number;
  computedMediaAlign: string;

  // Timeline-specific data
  items?: TimelinePropsModel['items'];
  activeItemIndex?: number;

  // Callbacks
  onScrollEnd: () => void;
  onThemeChange: () => void;
}

// ==========================================
// CONTEXT CREATION
// ==========================================

const TimelineContext = createContext<TimelineContextValue | null>(null);

// ==========================================
// PROVIDER PROPS AND COMPONENT
// ==========================================

export interface TimelineContextProviderProps extends Omit<
  Partial<TimelinePropsModel>,
  'children'
> {
  children: React.ReactNode;
  toolbarSearchConfig?: {
    width?: string;
    maxWidth?: string;
    minWidth?: string;
    inputWidth?: string;
    inputMaxWidth?: string;
  };
  googleFonts?: {
    fontFamily: string;
    elements?: {
      title?: { weight?: any; style?: any; size?: string };
      cardTitle?: { weight?: any; style?: any; size?: string };
      cardSubtitle?: { weight?: any; style?: any; size?: string };
      cardText?: { weight?: any; style?: any; size?: string };
      controls?: { weight?: any; style?: any; size?: string };
    };
    weights?: any[];
    display?: string;
    preconnect?: boolean;
  };
  i18nConfig?: TimelineI18nConfig;
}

export const TimelineContextProvider: FunctionComponent<
  TimelineContextProviderProps
> = (props) => {
  const {
    children,
    // Core props with defaults
    mode = 'VERTICAL_ALTERNATING',
    cardHeight = 200,
    cardWidth,
    cardLess = false,
    flipLayout,
    itemWidth = 200,
    lineWidth = 3,

    // Media props
    mediaHeight = 200,
    mediaSettings,

    // Timeline point props
    timelinePointDimension = 16,
    timelinePointShape = 'circle',

    // Interaction props
    disableNavOnKey = false,
    disableAutoScrollOnClick = false,
    disableInteraction = false,
    disableClickOnCircle = false,
    disableTimelinePoint = false,

    // UI feature props
    enableBreakPoint = true,
    enableDarkToggle = false,
    enableLayoutSwitch = true,
    enableQuickJump = true,
    focusActiveItemOnLoad = false,
    highlightCardsOnHover = false,

    // Cards and content props
    borderLessCards = false,
    cardPositionHorizontal,
    parseDetailsAsHTML = false,
    useReadMore = true,
    textOverlay,
    contentAlignment = { horizontal: 'left', vertical: 'top' },

    // Scrolling props (default aligns with legacy behavior: no scrollbar)
    scrollable = { scrollbar: false },

    // Toolbar props
    toolbarPosition = 'top',
    disableToolbar = false,
    toolbarSearchConfig,

    // Slideshow props
    slideItemDuration = 2000,
    showProgressOnSlideshow = true,
    showOverallSlideshowProgress,
    slideShow,
    slideShowType,

    // Other props
    titleDateFormat = 'MMM DD, YYYY',
    uniqueId = 'react-chrono',
    nestedCardHeight = 150,
    contentDetailsHeight = 10,
    responsiveBreakPoint = 1024,
    noUniqueId = false,
    isChild = false,

    // Dynamic props
    darkMode = false,
    showAllCardsHorizontal = false,
    textDensity = 'HIGH' as TextDensity,

    // Customization props
    theme,
    buttonTexts,
    classNames,
    fontSizes,
    semanticTags,

    // i18n props
    i18nConfig,

    // Data props
    items,
    activeItemIndex = 0,

    // Callbacks
    onScrollEnd,
    onThemeChange,
  } = props;

  // ==========================================
  // DYNAMIC STATE
  // ==========================================
  const [isDarkMode, setIsDarkMode] = useState(darkMode);
  const [showAllCards, setShowAllCards] = useState(
    mode === 'HORIZONTAL_ALL' ? true : showAllCardsHorizontal,
  );
  const [isMobileDetected, setIsMobileDetected] = useState(false);
  const [textContentDensity, setTextContentDensity] =
    useState<TextDensity>(textDensity);

  // ==========================================
  // CALLBACKS
  // ==========================================
  const toggleDarkMode = useCallback(() => {
    setIsDarkMode(!isDarkMode);
    onThemeChange?.();
  }, [isDarkMode, onThemeChange]);

  const updateShowAllCardsHorizontal = useCallback((state: boolean) => {
    setShowAllCards(state);
  }, []);

  const updateTextContentDensity = useCallback((density: TextDensity) => {
    setTextContentDensity(density);
  }, []);

  // ==========================================
  // MODE SYNCHRONIZATION
  // ==========================================
  // Sync internal darkMode state with prop changes
  useEffect(() => {
    setIsDarkMode(darkMode);
  }, [darkMode]);

  // Update showAllCardsHorizontal when mode or prop changes
  useEffect(() => {
    if (mode === 'HORIZONTAL_ALL') {
      setShowAllCards(true);
    } else if (mode === 'HORIZONTAL') {
      // Respect the incoming prop to allow HORIZONTAL + showAllCardsHorizontal
      setShowAllCards(showAllCardsHorizontal);
    }
  }, [mode, showAllCardsHorizontal]);

  // ==========================================
  // RESPONSIVE DETECTION
  // ==========================================
  useMatchMedia(`(max-width: ${responsiveBreakPoint - 1}px)`, {
    onMatch: () => setIsMobileDetected(true),
    enabled: enableBreakPoint,
  });

  useMatchMedia(`(min-width: ${responsiveBreakPoint}px)`, {
    onMatch: () => setIsMobileDetected(false),
    enabled: enableBreakPoint,
  });

  // ==========================================
  // COMPUTED VALUES
  // ==========================================
  const computedCardHeight = useMemo(() => {
    // FIX for Issue #498: Handle 'auto' cardHeight
    if (cardHeight === 'auto') {
      return 'auto';
    }
    return cardLess ? Math.min(cardHeight, 80) : cardHeight;
  }, [cardLess, cardHeight]);

  const computedActiveItemIndex = useMemo(
    () => (flipLayout && items ? items.length - 1 : 0),
    [flipLayout, items?.length],
  );

  const computedMediaAlign = useMemo(
    () => (mode === 'VERTICAL' && !textOverlay ? 'left' : 'center'),
    [mode, textOverlay],
  );

  // ==========================================
  // MEMOIZED OBJECTS
  // ==========================================
  const memoizedTheme = useMemo(
    () => ({
      ...getDefaultThemeOrDark(isDarkMode),
      ...theme,
    }),
    [isDarkMode, theme],
  );

  // Setup i18n helper first
  const i18nHelper = useI18n(i18nConfig);

  // Create text resolver with i18n and legacy support
  const textResolver = useMemo(
    () => createTextResolver(i18nHelper, buttonTexts),
    [i18nHelper, buttonTexts],
  );

  const memoizedButtonTexts = useMemo(
    () => ({
      ...getDefaultButtonTexts(),
      ...buttonTexts,
    }),
    [buttonTexts],
  );

  const memoizedClassNames = useMemo(
    () => ({
      ...getDefaultClassNames(),
      ...classNames,
    }),
    [classNames],
  );

  const memoizedFontSizes = useMemo(
    () => ({
      cardSubtitle: '0.85rem',
      cardText: '1rem',
      cardTitle: '1rem',
      title: '1rem',
      ...fontSizes,
    }),
    [fontSizes],
  );

  // Google Fonts integration
  const googleFontsConfig = useMemo(() => {
    // If no Google Fonts specified, use a default one
    if (!props.googleFonts) {
      return {
        fontFamily: 'Inter',
        elements: {
          title: { weight: 600, style: 'normal' },
          cardTitle: { weight: 500, style: 'normal' },
          cardSubtitle: { weight: 400, style: 'normal' },
          cardText: { weight: 400, style: 'normal' },
          controls: { weight: 500, style: 'normal' },
        },
        weights: [400, 500, 600],
        display: 'swap',
        preconnect: true,
      };
    }

    // If we have both fontSizes and googleFonts, merge them
    if (props.googleFonts) {
      return {
        ...props.googleFonts,
        elements: {
          ...props.googleFonts.elements,
          // Override sizes from fontSizes if provided
          ...(memoizedFontSizes.title && {
            title: {
              ...props.googleFonts.elements?.title,
              size: memoizedFontSizes.title,
            },
          }),
          ...(memoizedFontSizes.cardTitle && {
            cardTitle: {
              ...props.googleFonts.elements?.cardTitle,
              size: memoizedFontSizes.cardTitle,
            },
          }),
          ...(memoizedFontSizes.cardSubtitle && {
            cardSubtitle: {
              ...props.googleFonts.elements?.cardSubtitle,
              size: memoizedFontSizes.cardSubtitle,
            },
          }),
          ...(memoizedFontSizes.cardText && {
            cardText: {
              ...props.googleFonts.elements?.cardText,
              size: memoizedFontSizes.cardText,
            },
          }),
        },
      };
    }

    return null;
  }, [props.googleFonts, memoizedFontSizes]);

  const memoizedMediaSettings = useMemo(
    () => ({
      align: computedMediaAlign as 'left' | 'right' | 'center',
      fit: 'cover' as const,
      ...mediaSettings,
    }),
    [computedMediaAlign, mediaSettings],
  );

  const memoizedContentAlignment = useMemo(
    () => ({
      horizontal: contentAlignment.horizontal || ('left' as const),
      vertical: contentAlignment.vertical || ('top' as const),
    }),
    [contentAlignment],
  );

  const memoizedSemanticTags = useMemo(
    () => ({
      cardTitle: 'span' as const,
      cardSubtitle: 'span' as const,
      ...semanticTags,
    }),
    [semanticTags],
  );

  const memoizedSlideShowType = useMemo(
    () => slideShowType ?? getSlideShowType(mode),
    [slideShowType, mode],
  );

  // ==========================================
  // CONTEXT VALUE
  // ==========================================
  const contextValue = useMemo(
    (): TimelineContextValue => ({
      // Static configuration
      mode,
      cardHeight,
      cardWidth: cardWidth || 400,
      cardLess,
      flipLayout: flipLayout || false,
      itemWidth,
      lineWidth,
      mediaHeight,
      mediaSettings: memoizedMediaSettings,
      timelinePointDimension,
      timelinePointShape,
      disableNavOnKey,
      disableAutoScrollOnClick: disableAutoScrollOnClick || disableInteraction,
      disableInteraction,
      disableClickOnCircle: disableClickOnCircle || disableInteraction,
      disableTimelinePoint: disableTimelinePoint || disableInteraction,
      enableBreakPoint,
      enableDarkToggle,
      enableLayoutSwitch,
      enableQuickJump,
      focusActiveItemOnLoad,
      highlightCardsOnHover,
      borderLessCards,
      cardPositionHorizontal: cardPositionHorizontal ?? 'BOTTOM',
      parseDetailsAsHTML,
      useReadMore,
      textOverlay: textOverlay || false,
      contentAlignment: memoizedContentAlignment,
      scrollable,
      toolbarPosition,
      disableToolbar,
      toolbarSearchConfig,
      slideItemDuration,
      showProgressOnSlideshow: showProgressOnSlideshow && !!slideShow,
      showOverallSlideshowProgress: showOverallSlideshowProgress ?? !!slideShow,
      titleDateFormat,
      uniqueId,
      nestedCardHeight,
      contentDetailsHeight: Math.max(contentDetailsHeight, mediaHeight * 0.75),
      responsiveBreakPoint,
      noUniqueId,
      isChild,

      // Dynamic state
      isDarkMode,
      isMobile: isMobileDetected,
      showAllCardsHorizontal: showAllCards,
      textContentDensity,
      toggleDarkMode,
      updateShowAllCardsHorizontal,
      updateTextContentDensity,

      // Memoized objects
      theme: memoizedTheme,
      buttonTexts: memoizedButtonTexts,
      classNames: memoizedClassNames,
      fontSizes: memoizedFontSizes,
      semanticTags: memoizedSemanticTags,
      slideShowType: memoizedSlideShowType,
      googleFonts: googleFontsConfig,
      i18nConfig,
      i18nHelper,
      textResolver,

      // Computed values
      computedCardHeight,
      computedActiveItemIndex,
      computedMediaAlign,

      // Timeline-specific data
      items,
      activeItemIndex,

      // Callbacks
      onScrollEnd: onScrollEnd || (() => {}),
      onThemeChange: onThemeChange || (() => {}),
    }),
    [
      // Static config dependencies
      mode,
      cardHeight,
      cardWidth,
      cardLess,
      flipLayout,
      itemWidth,
      lineWidth,
      mediaHeight,
      memoizedMediaSettings,
      memoizedContentAlignment,
      timelinePointDimension,
      timelinePointShape,
      disableNavOnKey,
      disableAutoScrollOnClick,
      disableInteraction,
      disableClickOnCircle,
      disableTimelinePoint,
      enableBreakPoint,
      enableDarkToggle,
      enableLayoutSwitch,
      enableQuickJump,
      focusActiveItemOnLoad,
      highlightCardsOnHover,
      borderLessCards,
      cardPositionHorizontal,
      parseDetailsAsHTML,
      useReadMore,
      textOverlay,
      contentAlignment,
      scrollable,
      toolbarPosition,
      disableToolbar,
      toolbarSearchConfig,
      slideItemDuration,
      showProgressOnSlideshow,
      showOverallSlideshowProgress,
      slideShow,
      titleDateFormat,
      uniqueId,
      nestedCardHeight,
      contentDetailsHeight,
      responsiveBreakPoint,
      noUniqueId,
      isChild,

      // Dynamic state dependencies
      isDarkMode,
      isMobileDetected,
      showAllCards,
      textContentDensity,
      toggleDarkMode,
      updateShowAllCardsHorizontal,
      updateTextContentDensity,

      // Memoized objects dependencies
      memoizedTheme,
      memoizedButtonTexts,
      memoizedClassNames,
      memoizedFontSizes,
      memoizedSemanticTags,
      memoizedSlideShowType,
      googleFontsConfig,
      i18nConfig,
      textResolver,

      // Computed values dependencies
      computedCardHeight,
      computedActiveItemIndex,
      computedMediaAlign,

      // Data dependencies
      items,
      activeItemIndex,

      // Callback dependencies
      onScrollEnd,
      onThemeChange,
    ],
  );

  return (
    <TimelineContext.Provider value={contextValue}>
      {children}
    </TimelineContext.Provider>
  );
};

// ==========================================
// CONTEXT HOOK
// ==========================================

/**
 * Hook to access the timeline context
 */
export const useTimelineContext = (): TimelineContextValue => {
  const context = useContext(TimelineContext);

  if (!context) {
    throw new Error(
      'useTimelineContext must be used within a TimelineContextProvider',
    );
  }

  return context;
};

/**
 * Hook to access only static configuration (performance optimized)
 */
export const useTimelineStaticConfig = (): TimelineStaticConfig => {
  const context = useTimelineContext();

  return useMemo(
    () => ({
      mode: context.mode,
      cardHeight: context.cardHeight,
      cardWidth: context.cardWidth || 400,
      cardLess: context.cardLess,
      flipLayout: context.flipLayout || false,
      itemWidth: context.itemWidth,
      lineWidth: context.lineWidth,
      mediaHeight: context.mediaHeight,
      mediaSettings: context.mediaSettings,
      timelinePointDimension: context.timelinePointDimension,
      timelinePointShape: context.timelinePointShape,
      disableNavOnKey: context.disableNavOnKey,
      disableAutoScrollOnClick: context.disableAutoScrollOnClick,
      disableInteraction: context.disableInteraction,
      disableClickOnCircle: context.disableClickOnCircle,
      disableTimelinePoint: context.disableTimelinePoint,
      enableBreakPoint: context.enableBreakPoint,
      enableDarkToggle: context.enableDarkToggle,
      enableLayoutSwitch: context.enableLayoutSwitch,
      enableQuickJump: context.enableQuickJump,
      focusActiveItemOnLoad: context.focusActiveItemOnLoad,
      highlightCardsOnHover: context.highlightCardsOnHover,
      borderLessCards: context.borderLessCards,
      cardPositionHorizontal: context.cardPositionHorizontal,
      parseDetailsAsHTML: context.parseDetailsAsHTML,
      useReadMore: context.useReadMore,
      textOverlay: context.textOverlay,
      contentAlignment: context.contentAlignment,
      scrollable: context.scrollable,
      toolbarPosition: context.toolbarPosition,
      disableToolbar: context.disableToolbar,
      toolbarSearchConfig: context.toolbarSearchConfig,
      slideItemDuration: context.slideItemDuration,
      showProgressOnSlideshow: context.showProgressOnSlideshow,
      showOverallSlideshowProgress: context.showOverallSlideshowProgress,
      titleDateFormat: context.titleDateFormat,
      uniqueId: context.uniqueId,
      nestedCardHeight: context.nestedCardHeight,
      contentDetailsHeight: context.contentDetailsHeight,
      responsiveBreakPoint: context.responsiveBreakPoint,
      noUniqueId: context.noUniqueId,
      isChild: context.isChild,
    }),
    [context],
  );
};

/**
 * Hook to access only dynamic state (performance optimized)
 */
export const useTimelineDynamicState = (): TimelineDynamicState => {
  const context = useTimelineContext();

  return useMemo(
    () => ({
      isDarkMode: context.isDarkMode,
      isMobile: context.isMobile,
      showAllCardsHorizontal: context.showAllCardsHorizontal,
      textContentDensity: context.textContentDensity,
      toggleDarkMode: context.toggleDarkMode,
      updateShowAllCardsHorizontal: context.updateShowAllCardsHorizontal,
      updateTextContentDensity: context.updateTextContentDensity,
    }),
    [context],
  );
};

/**
 * Hook to access only memoized objects (performance optimized)
 */
export const useTimelineMemoizedObjects = (): TimelineMemoizedObjects => {
  const context = useTimelineContext();

  return useMemo(
    () => ({
      theme: context.theme,
      buttonTexts: context.buttonTexts,
      classNames: context.classNames,
      fontSizes: context.fontSizes,
      isDarkMode: context.isDarkMode,
      semanticTags: context.semanticTags,
      slideShowType: context.slideShowType,
      googleFonts: context.googleFonts,
      i18nConfig: context.i18nConfig,
      i18nHelper: context.i18nHelper,
      textResolver: context.textResolver,
    }),
    [context],
  );
};
